package jcu.salt.io;

import java.io.IOException;

import jcu.salt.Configuration;
import jcu.salt.Logger;

import com.rbnb.sapi.SAPIException;
import com.rbnb.sapi.Source;

/**
 * Provides convenient access to a ring buffer for sending data as byte array.
 * 
 * Therefore it makes use of the configured values available
 * by {@link Configuration} for the turbine modes/cache/etc.
 * 
 * @author SAL-T team
 */
public class DataTurbineWriteConnector extends DataTurbineConnector {

	private static Source source = null;
	private static int connectionCounter = 0;

	public DataTurbineWriteConnector(String host, String source, String channel) {
		super(host, source, channel);
		init();
	}

	protected void init() {		
		Configuration config = Configuration.getInstance();

		try {
			// source = new Source(); // Default source is 100-frame cache, no
			// archive
			if (source == null) {
				Logger.log("Starting connection to Turbine...");
				source = new Source(new Integer(config
						.get(Configuration.CACHESIZE)).intValue(), config
						.get(Configuration.ARCHIVEMODE), new Integer(config
						.get(Configuration.ARCHIVESIZE)).intValue());
				source.OpenRBNBConnection(getHost(), getSource());
			} else {
				Logger.log("Make use of existing connection to Turbine...");
			}
			connectionCounter++;
			setConnected(true);
		} catch (SAPIException se) {
			System.err.println("Error on Turbine - not connected");
			setConnected(false);
			return;
		}

		// The channel map is constant once set up, so only do it once
		try {
			setChannelIndex(getChannelMap().Add(getChannel()));
			Logger.log("Turbine created channel: " + getSource() + "/"
					+ getChannel());
		} catch (SAPIException se) {
			System.err.println("Error adding to channel map!");
			return;
		}
		// System.out.println("init done for chanIndex " + getChannnelIndex());
	}

	public void flush() throws IOException {
		try {
			source.Flush(getChannelMap(), false);
		} catch (SAPIException e) {
			System.out.println("Error saving data!");
		}
	}
	
	public void write(byte[] b) throws IOException {
		try {
			getChannelMap().PutTimeAuto("timeofday");
			getChannelMap().PutMime(getChannnelIndex(),
					"application/octet-stream");
			getChannelMap().PutDataAsByteArray(getChannnelIndex(), b);
			flush();
		} catch (SAPIException mse) {
			System.err.println("Error saving data!");
		}
	}
	
	

	public void close() throws IOException {
		if (isConnected() && source != null) {
			connectionCounter--;
			if (connectionCounter == 0) {
				Logger.log("Closing RBNB connection");
				source.Detach();
				source.CloseRBNBConnection();
				source = null;
				setConnected(false);
			}
		}
	}
}
